package cn.laixueit.service.impl;

import cn.laixueit.CacheKey;
import cn.laixueit.crawlerutil.CrawlerUtil;
import cn.laixueit.mapper.BookMapper;
import cn.laixueit.mapper.ChapterMapper;
import cn.laixueit.pojo.Book;
import cn.laixueit.pojo.Chapter;
import cn.laixueit.service.ChapterService;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ChapterServiceImpl implements ChapterService {

    @Autowired
    private ChapterMapper chapterMapper;
    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private SqlSession sqlSession;

    @Override
    public void add(List<Map> mapChapterList, Integer BookId) {
        List<Chapter> chapterList = new ArrayList<>();

        Example example = new Example(Chapter.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("bookId", BookId);

        // 获取数据库中当前小说的所有章节
        List<Chapter> dbchapters = chapterMapper.selectByExample(example);

        if (mapChapterList.size() != dbchapters.size()) {
            // 将数据库中的数据转换成一个集合map
            List<Map> list = new ArrayList();
            for (Chapter chapter : dbchapters) {
                Map map = new HashMap();
                map.put("chapter", chapter.getChapter());
                map.put("linkUrl", chapter.getLinkUrl());
                map.put("sort", chapter.getSort());
                list.add(map);
            }

            // 爬取的和数据库的差集
            mapChapterList.removeAll(list);

            // 将差集转换为集合chapter
            for (Map map : mapChapterList) {
                Chapter chapter = new Chapter();
                chapter.setChapter((String) map.get("chapter"));
                chapter.setLinkUrl("http://www.xbiquge.la" + (String) map.get("linkUrl"));
                chapter.setSort((Integer) map.get("sort"));
                chapter.setBookId(BookId);
                chapterList.add(chapter);
            }

            // 批量保存差集
            chapterMapper.insertList(chapterList);
            sqlSession.clearCache();
        }
    }

    // 根据书籍id查询所有章节
    public List<Chapter> findByBookId(Integer bookId) {

        List<Chapter> redisChapterlist = (List<Chapter>) redisTemplate.boundHashOps(CacheKey.CHAPTER).get(bookId);

        if(redisChapterlist==null || redisChapterlist.size()==0){ // redis没有数据
            Example example = new Example(Chapter.class);
            example.setOrderByClause("sort");
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("bookId", bookId);
            List<Chapter> dbchapterList = chapterMapper.selectByExample(example);
            if(dbchapterList==null || dbchapterList.size()==0){ // 数据库也没有数据
                // 获取当前小说所有章节页面对应的url
                Book book = bookMapper.selectByPrimaryKey(bookId);
                // 都没有数据就去爬取
                List<Map> mapChapterList = CrawlerUtil.getBookChapter(book.getLinkUrl());
                // 调用方法将该书所有章节存入数据库
                add(mapChapterList,book.getId());
                // 再去数据库查询所有章节
                dbchapterList = chapterMapper.selectByExample(example);
            }
            // 存入缓存
            redisTemplate.boundHashOps(CacheKey.CHAPTER).put(bookId,dbchapterList);

            return dbchapterList;
        }
        return redisChapterlist;
    }

    @Override
    public Chapter findById(Integer id) {
        return chapterMapper.selectByPrimaryKey(id);
    }


    @Autowired
    private BookMapper bookMapper;


    // 缓存所有章节
    public void cache() {
        redisTemplate.delete(CacheKey.CHAPTER);
        List<Book> bookList = bookMapper.selectAll();
        for (Book book : bookList) {
            Example example = new Example(Chapter.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("bookId", book.getId());
            List<Chapter> chapterList = chapterMapper.selectByExample(example);
            redisTemplate.boundHashOps(CacheKey.CHAPTER).put(book.getId(),chapterList);
        }
    }
}
